#ifndef _COMUTILIY_CCHANNEL_HPP_
#define _COMUTILIY_CCHANNEL_HPP_

#include <comutiliy/asynio.h>

class CChannel 
{
public:
	CChannel(void) {

	}
	virtual ~CChannel(void) {

	}

	std_method_impl CreateCChannel(IBase *pRot) {

		HRESULT hr = S_OK;
		rc_assert(pRot != NULL, E_FAIL)

		hr = pRot->QueryInterface(IID_IComRunningObjectTable, (void**)&m_pRot);
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pRot->GetObject(CLSID_IAsynFrame, IID_IAsynFrame, (IBase**)&m_pIAsynFrame);
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pIAsynFrame->CreateIo(io_tcp_socket, (IBase**)&m_pISockket);
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pIAsynFrame->CreateIo(io_operation, (IBase**)&m_pIWriteOperation);
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pIAsynFrame->CreateIo(io_operation, (IBase**)&m_pIReadOperation);
		rc_assert(hr == S_OK, E_FAIL)

		return hr;
	}
	std_method_impl AttachCChannel(IBase *pRot, IBase* pSocket) {

		HRESULT hr = S_OK;
		rc_assert(pRot != NULL, E_FAIL)
		rc_assert(pSocket != NULL, E_FAIL)

		hr = pRot->QueryInterface(IID_IComRunningObjectTable, (void**)&m_pRot);
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pRot->GetObject(CLSID_IAsynFrame, IID_IAsynFrame, (IBase**)&m_pIAsynFrame);
		rc_assert(hr == S_OK, E_FAIL)

		hr = pSocket->QueryInterface(IID_ITcpSocket, (void**)&m_pISockket);
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pIAsynFrame->CreateIo(io_operation, (IBase**)&m_pIWriteOperation);
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pIAsynFrame->CreateIo(io_operation, (IBase**)&m_pIReadOperation);
		rc_assert(hr == S_OK, E_FAIL)

		hr = SetInterface();
		rc_assert(hr == S_OK, E_FAIL)

		return hr;
	}
	std_method_impl OpenCChannel() {

		HRESULT hr = S_OK;

		hr = m_pISockket->CreateSock();
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pISockket->OpenIo();
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pISockket->BindIo();
		rc_assert(hr == S_OK, E_FAIL)

		return hr;
	}
	std_method_impl BindEvent(IBase* pBase) {

		rc_assert(m_pIWriteOperation != NULL, E_FAIL)
		rc_assert(m_pIReadOperation != NULL, E_FAIL)

		HRESULT hr = S_OK;

		hr = m_pIWriteOperation->BindEvent(pBase);
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pIReadOperation->BindEvent(pBase);
		rc_assert(hr == S_OK, E_FAIL)

		return hr;
	}
	std_method_impl UnBindEvent() {

		rc_assert(m_pIWriteOperation != NULL, E_FAIL)
		rc_assert(m_pIReadOperation != NULL, E_FAIL)

		HRESULT hr = S_OK;

		hr = m_pIWriteOperation->UnBindEvent();
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pIReadOperation->UnBindEvent();
		rc_assert(hr == S_OK, E_FAIL)

		return hr;
	}
	std_method_impl ConnectChannel(LPCSTR addr, int len, event_id event) {

		rc_assert(addr != NULL, E_FAIL)
		rc_assert(len != 0, E_FAIL)

		HRESULT hr = S_OK;

		CharArrayPtr item;
		item.dispose();
		item = ALLOC_NEW char[BROKER_ADDR_MAXLEN + 1]();
		rc_assert(item.m_p != NULL, E_FAIL)
		s_strcpy(item, BROKER_ADDR_MAXLEN, addr);

		char* port = NULL;
		char* ip = NULL;

		ip = s_strtok(item, ":", &port);
		rc_assert(ip != NULL, E_FAIL)
		rc_assert(port != NULL, E_FAIL)
		rc_assert(m_pISockket != NULL, E_FAIL)

		return m_pISockket->ConnectIo(ip, atoi(port), m_pIWriteOperation, event);
	}
	std_method_impl CloseChannel() {

		rc_assert(m_pISockket != NULL, E_FAIL)
		rc_assert(m_pIWriteOperation != NULL, E_FAIL)
		rc_assert(m_pIReadOperation != NULL, E_FAIL)

		HRESULT hr = S_OK;

		hr = m_pISockket->CloseIo(CLOSE_BOTH_IO);
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pISockket->CloseSock();
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pIWriteOperation->UnBindEvent();
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pIReadOperation->UnBindEvent();
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pIWriteOperation->UnBindIBase();
		rc_assert(hr == S_OK, E_FAIL)

		hr = m_pIReadOperation->UnBindIBase();
		rc_assert(hr == S_OK, E_FAIL)

		m_pIWriteOperation.dispose();

		m_pIReadOperation.dispose();

		m_pISockket.dispose();

		m_pIAsynFrame.dispose();

		m_pRot.dispose();

		return S_OK;
	}
	std_method_type_impl(BUFFER_SIZE) ReadChannel(BUFFER_PTR buf, BUFFER_SIZE size) {

		rc_assert(m_pISockket != NULL, E_FAIL)
		return this->m_pISockket->SyncRecv(buf, size);
	}
	std_method_type_impl(BUFFER_SIZE) WriteChannel(BUFFER_PTR buf, BUFFER_SIZE size) {

		rc_assert(m_pISockket != NULL, E_FAIL)
		return this->m_pISockket->SyncSend(buf, size);
	}
	std_method_impl OnReadChannel(ULONG pos, ULONG size, event_id event) {

		rc_assert(m_pISockket != NULL, E_FAIL)
		rc_assert(m_pIReadOperation != NULL, E_FAIL)
		rc_assert(size != 0, E_FAIL)
		rc_assert(m_pIReadOperation->SetIoParam(pos, size) == S_OK, E_FAIL)
	

		return this->m_pISockket->ReadIo(m_pIReadOperation, event);
	}
	std_method_impl OnWriteChannel(ULONG pos, ULONG size, event_id event) {

		rc_assert(m_pISockket != NULL, E_FAIL)
		rc_assert(m_pIWriteOperation != NULL, E_FAIL)
		rc_assert(size != 0, E_FAIL)
		rc_assert(m_pIWriteOperation->SetIoParam(pos, size) == S_OK, E_FAIL)

		return this->m_pISockket->WriteIo(m_pIWriteOperation, event);
	}
	std_method_impl WriteStream(BUFFER_PTR Ptr, BUFFER_SIZE Pos, BUFFER_SIZE Size) {

		rc_assert(m_pIWriteOperation != NULL, E_FAIL)
		return this->m_pIWriteOperation->Attach(Ptr, Pos, Size);
	}

	std_method_impl ReadStream(BUFFER_PTR Ptr, BUFFER_SIZE Pos, BUFFER_SIZE Size) {

		rc_assert(m_pIReadOperation != NULL, E_FAIL)
		return this->m_pIReadOperation->Attach(Ptr, Pos, Size);
	}
	std_method_impl GetWritePtr(BUFFER_PTR* Ptr) {

		rc_assert(m_pIWriteOperation != NULL, E_FAIL)
		return this->m_pIWriteOperation->GetPtr(Ptr);
	}

	std_method_impl GetReadPtr(BUFFER_PTR* Ptr) {

		rc_assert(m_pIReadOperation != NULL, E_FAIL)
		return this->m_pIReadOperation->GetPtr(Ptr);
	}
	std_method_impl GetObject(IBase *pIBase, OperationPtr& pOperation)
	{
		HRESULT hr = S_OK;

		hr = pIBase->QueryInterface(IID_IOperation, (void**)&pOperation);
		rc_assert(hr == S_OK, E_FAIL)

		return hr;
	}
private:
	std_method_impl SetInterface() {

		rc_assert(m_pISockket != NULL, E_FAIL)
		rc_assert(m_pIWriteOperation != NULL, E_FAIL)
		rc_assert(m_pIReadOperation != NULL, E_FAIL)

		HRESULT hr = S_OK;

		_lComPtr<IBase> pBase;
		hr = m_pISockket->QueryInterface(IID_IBase, (void**)&pBase);
		rc_assert(hr == S_OK, E_FAIL)

		hr = this->m_pIWriteOperation->BindIBase(pBase);
		rc_assert(hr == S_OK, E_FAIL)

		hr = this->m_pIReadOperation->BindIBase(pBase);
		rc_assert(hr == S_OK, E_FAIL)

		return hr;

	}
	std_method_impl UnSetInterface() {

		rc_assert(m_pIWriteOperation != NULL, E_FAIL)
		rc_assert(m_pIReadOperation != NULL, E_FAIL)

		HRESULT hr = S_OK;

		hr = this->m_pIWriteOperation->UnBindIBase();
		rc_assert(hr == S_OK, E_FAIL)

		hr = this->m_pIReadOperation->UnBindIBase();
		rc_assert(hr == S_OK, E_FAIL)

		return S_OK;
	}
protected:
	_lComPtr<IComRotMessage>			m_pRot;
	AsynFramePtr						m_pIAsynFrame;
	TcpSocketPtr						m_pISockket;
	OperationPtr						m_pIWriteOperation;
	OperationPtr						m_pIReadOperation;

};


#endif

